mermaid
graph TD
    A[开始] --> B{创建 WavPlayer 对象};
    B --> C{调用 player.Load()};
    C --> D{文件是否存在?};
    D -- 否 --> E[打印 "无法打开文件"];
    D -- 是 --> F{读取并验证 RIFF/WAVE 头};
    F --> G{头信息是否有效?};
    G -- 否 --> H[打印 "无效的WAV文件格式"];
    G -- 是 --> I{循环查找 'fmt ' 块};
    I --> J{读取音频格式 (WAVEFORMATEX)};
    J --> K{循环查找 'data' 块};
    K --> L{读取音频数据到内存};
    L --> M{Load() 执行成功?};
    M -- 否 --> Z[结束];
    M -- 是 --> N{调用 player.Play()};
    N --> O{打开音频输出设备};
    O --> P{设备是否成功打开?};
    P -- 否 --> Q[打印 "无法打开音频输出设备"];
    P -- 是 --> R{准备音频头 (WAVEHDR)};
    R --> S{音频头是否准备成功?};
    S -- 否 --> T[打印 "无法准备音频头"];
    S -- 是 --> U{写入音频数据播放 (waveOutWrite)};
    U --> V{写入是否成功?};
    V -- 否 --> W[打印 "无法播放音频"];
    V -- 是 --> X{循环等待播放完成};
    X --> Y[打印 "音频播放完成"];
    
    subgraph "Load() 过程"
        D
        F
        G
        I
        J
        K
        L
    end

    subgraph "Play() 过程"
        O
        P
        R
        S
        U
        V
        X
    end

    E --> Z;
    H --> Z;
    Q --> Z;
    T --> Z;
    W --> Z;
    Y --> Z;

    sequenceDiagram
    participant S as 发送端(rtp_sender)
    participant R as 接收端(rtp_receiver)
    participant A as 音频设备

    Note over S: 初始化 Winsock
    Note over S: 打开并读取WAV文件
    Note over S: 解析音频格式(fmt块)
    Note over S: 读取音频数据(data块)
    Note over S: 创建UDP Socket
    
    Note over R: 初始化 Winsock
    Note over R: 创建UDP Socket
    Note over R: 初始化音频设备
    Note over R: 创建预缓存区

    loop 音频数据分包发送
        S->>R: 发送RTP包(1024字节)
        Note over S: 计算延时
        Note over S: Sleep控制发送速率
        R->>R: 将数据存入缓存
        alt 缓存已满
            R->>A: 开始音频播放
            Note over R: 边接收边播放
        end
    end

    Note over S: 发送完成
    Note over S: 清理资源
    Note over R: 播放完成
    Note over R: 清理资源
